﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		Template.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 // 
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Dexter.Services;
using Topics.Radical.Validation;

namespace Dexter.Services.Implementation {
	/// <summary>
	/// 	Implementation of <see cref = "ITemplate" />.
	/// </summary>
	public abstract class Template : ITemplate {
		const string MASTER_TEMPLATE = "DEXTER-TEMPLATE-MASTER-TEMPLATE";
		static IDictionary <string , string> defaultValues;
		readonly ILogger logger;

		readonly IList <string> markers;
		readonly IDictionary <string , string> parsedSection;
		readonly string templateFilePath;
		readonly string templateMasterFilePath;
		readonly string templateName;
		readonly string masterText;
		readonly string templateText;

		/// <summary>
		/// Initializes a new instance of the <see cref="Template"/> class.
		/// </summary>
		/// <param name="templateName">Name of the template.</param>
		/// <param name="blogTheme">The blog theme.</param>
		/// <param name="logger">The logger.</param>
		/// <param name="configurationService">The configuration service.</param>
		/// <param name="urlBuilderBase">The URL builder base.</param>
		/// <param name="themeManager">The theme manager.</param>
		protected Template ( string templateName , IBlogTheme blogTheme , ILogger logger , IConfigurationService configurationService , IUrlBuilderBase urlBuilderBase, IThemeManager themeManager ) {
			this.logger = logger;
			this.markers = new List<string> ( );
			this.parsedSection = new Dictionary<string, string> ( );

			Ensure.That ( templateName )
				.Named ( "templateName" )
				.WithPreview ( ( v , e ) => this.logger.Warn ( v.GetFullErrorMessage ( ) , e ) )
				.IsNotNullNorEmpty ( )
				.WithMessage ( "Invalid template file name." );

			if (blogTheme == null)
				blogTheme = themeManager.GetThemeByName ( configurationService.Configuration.ThemeName );


			this.templateName = templateName;

			this.templateFilePath = blogTheme.TemplateFilePath ( this.templateName );

			if ( !File.Exists ( this.templateFilePath ) ) {
				throw new FileNotFoundException ( "File not found." , this.templateFilePath );
			}

			templateText = File.ReadAllText ( this.templateFilePath );

			this.templateMasterFilePath = blogTheme.TemplateMasterFilePath ( ExtractSection ( templateText, MASTER_TEMPLATE ) );

			if ( !File.Exists ( this.templateMasterFilePath ) ) {
				throw new FileNotFoundException ( "File not found." , this.templateMasterFilePath );
			}

			masterText = File.ReadAllText ( this.templateMasterFilePath );

			AddDefaultValue ( configurationService.Configuration , urlBuilderBase );
		}

		protected IDictionary <string , string> DefaultValues {
			get { return defaultValues; }
		}

		///<summary>
		///	Gets the name of the template.
		///</summary>
		///<example>
		///	Dexter.User.Notification.NewUserRegistered
		///</example>
		///<value>The name.</value>
		public virtual string Name {
			get { return templateName; }
		}

		/// <summary>
		/// 	Extracts the section.
		/// </summary>
		/// <param name = "sectionName">Name of the section.</param>
		/// <returns></returns>
		protected string ExtractSection ( string sectionName ) {
			return ExtractSection ( templateText, sectionName );
		}

		protected string MergeWithMaster(string sectionName) {
			var masterBody = ExtractSection ( masterText,"DEXTER-TEMPLATE-BODY" );

			return masterBody.Replace ( "$CONTENT$", ExtractSection ( sectionName ) );
		}

		string ExtractSection ( string container , string sectionName ) {
			if ( parsedSection.ContainsKey ( sectionName ) ) {
				return parsedSection[ sectionName ];
			}

			var returnData = container.ExtractTextBlock ( sectionName );

			parsedSection[ container + "_" + sectionName ] = returnData;

			return returnData;
		}

		static void AddDefaultValue ( SiteConfiguration configuration , IUrlBuilderBase urlBuilderBase ) {
			if ( defaultValues != null ) {
				return;
			}

			defaultValues = new Dictionary <string , string> ( );

			if ( !defaultValues.ContainsKey ( "BlogName" ) ) {
				defaultValues.Add ( "BlogName" , configuration.BlogName );
			}

			if ( !defaultValues.ContainsKey ( "PrincipalAuthor" ) ) {
				defaultValues.Add ( "PrincipalAuthor" , configuration.PrincipalAuthor );
			}

			if ( !defaultValues.ContainsKey ( "SiteTitle" ) ) {
				defaultValues.Add ( "SiteTitle" , configuration.SeoConfiguration.DefaultTitle );
			}

			if ( !defaultValues.ContainsKey ( "SiteDescription" ) ) {
				defaultValues.Add ( "SiteDescription" , configuration.SeoConfiguration.DefaultDescription );
			}

			if ( !defaultValues.ContainsKey ( "CopyRight" ) ) {
				defaultValues.Add ( "CopyRight" , configuration.SeoConfiguration.CopyRight );
			}

			if ( !defaultValues.ContainsKey ( "SourceUrl" ) ) {
				defaultValues.Add ( "SourceUrl" , urlBuilderBase.HomePage.ToString ( ) );
			}

			if ( !defaultValues.ContainsKey ( "SiteFeedUrl" ) ) {
				defaultValues.Add ( "SiteFeedUrl" , urlBuilderBase.FeedUrl );
			}

			if ( !defaultValues.ContainsKey ( "CurrentUser" ) ) {
				defaultValues.Add ( "CurrentUser" , Thread.CurrentPrincipal.Identity.Name );
			}
		}
	}
}
